/*
 * response_body_view.c
 * This file is part of gURL
 *
 * Copyright (C) 2014 - Aleksey Konovalov
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Library General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "response_body_view.h"

#include "body_visualizer.h"
#include "hex_body_visualizer.h"
#include "image_body_visualizer.h"
#include "json_body_visualizer.h"
#include "text_body_visualizer.h"
#include "web_body_visualizer.h"

struct _ResponseBodyView {
    GtkBox parent;
    GtkWidget* current_visualizer;
    GtkWidget* buttons;
    GPtrArray* visualizers;
    Session* session;
};

struct _ResponseBodyViewClass {
    GtkBoxClass parent;
};

static void response_body_view_interface_init(BodyVisualizerInterface* iface);

G_DEFINE_TYPE(ResponseBodyView, response_body_view, GTK_TYPE_BOX)

static void change_button_visibility(GtkWidget* button, gpointer data) {
    int* visinfo = data;
    int* btn_id = visinfo;
    int* current_visualizer = visinfo + 1;
    int* vis_compatible = visinfo + 2;

    gtk_widget_set_visible(button, vis_compatible[*btn_id]);
    if(*btn_id == *current_visualizer) {
        GtkToggleButton* tbtn = GTK_TOGGLE_BUTTON(button);
        if(gtk_toggle_button_get_active(tbtn))
            gtk_toggle_button_toggled(tbtn);
        else
            gtk_toggle_button_set_active(tbtn, TRUE);
    }
    ++(*btn_id); // switch to the next button
}

void response_body_view_change_session(ResponseBodyView* self,
                                       Session* session) {
    self->session = session;

    int data[self->visualizers->len + 2];
    int* loop_index = data;
    int* current_visualizer = data + 1;
    int* vis_compatible = data + 2;

    int selected_visualizer = 0;
    gboolean current_compatible = FALSE;
    for(guint i = self->visualizers->len; i > 0; --i) {
        BodyVisualizer* vis = g_ptr_array_index(self->visualizers, i - 1);
        vis_compatible[i - 1] = body_visualizer_check_is_compatible(vis, session);
        if(vis_compatible[i - 1] && !current_compatible) {
            selected_visualizer = i - 1;
            current_compatible |= (GTK_WIDGET(vis) == self->current_visualizer);
        }
    }

    *loop_index = 0; // the index of the button in the foreach loop
    *current_visualizer = selected_visualizer;
    gtk_container_foreach(GTK_CONTAINER(self->buttons),
                          change_button_visibility, data);
}

static void response_body_switch_view(ResponseBodyView* self,
                                      BodyVisualizer* visualizer) {
    if(self->current_visualizer)
        gtk_container_remove(GTK_CONTAINER(self), GTK_WIDGET(self->current_visualizer));
    self->current_visualizer = GTK_WIDGET(visualizer);
    g_object_ref(self->current_visualizer);
    body_visualizer_change_session(visualizer, self->session);
    gtk_container_add(GTK_CONTAINER(self), self->current_visualizer);
}

static void on_button_toggled(GtkToggleButton* button,
                              gpointer user_data) {
    BodyVisualizer* v = BODY_VISUALIZER(user_data);
    ResponseBodyView* rbv = RESPONSE_BODY_VIEW(
        gtk_widget_get_parent(
            gtk_widget_get_parent(GTK_WIDGET(button))));
    response_body_switch_view(rbv, v); 
}

static void response_body_view_init(ResponseBodyView* self) {
    self->visualizers = g_ptr_array_new_full(4, g_object_unref);
#ifdef HAVE_JSON_GLIB
    g_ptr_array_add(self->visualizers, json_body_visualizer_new());
#endif
    g_ptr_array_add(self->visualizers, image_body_visualizer_new());
    g_ptr_array_add(self->visualizers, text_body_visualizer_new());
#ifdef HAVE_GHEX
    g_ptr_array_add(self->visualizers, hex_body_visualizer_new());
#endif
#ifdef HAVE_GTKHTML
    g_ptr_array_add(self->visualizers, web_body_visualizer_new());
#endif
    g_ptr_array_foreach(self->visualizers, (GFunc)gtk_widget_show, NULL);

    self->buttons = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    g_object_set(G_OBJECT(self->buttons), "margin", 7, "margin-right", 3, NULL);
    GSList* grp = NULL;
    for(size_t i = 0; i < self->visualizers->len; ++i) {
        BodyVisualizer* bv = g_ptr_array_index(self->visualizers, i);
        gtk_widget_set_hexpand(GTK_WIDGET(bv), TRUE);
        gtk_widget_set_vexpand(GTK_WIDGET(bv), TRUE);
        GtkWidget* btn = gtk_radio_button_new_with_label(
                            grp, body_visualizer_get_name(bv));
        g_signal_connect(btn, "toggled", G_CALLBACK(on_button_toggled), bv);
        grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(btn));
        gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(btn), FALSE);
        gtk_container_add(GTK_CONTAINER(self->buttons), btn);
    }
    gtk_container_add(GTK_CONTAINER(self), self->buttons);
    gtk_widget_show_all(self->buttons);

    response_body_switch_view(self, g_ptr_array_index(self->visualizers, 0));
}

static void response_body_view_dispose(GObject* object) {
    ResponseBodyView* bv = RESPONSE_BODY_VIEW(object);
    bv->current_visualizer = NULL;
    g_ptr_array_unref(bv->visualizers);
}

static void response_body_view_class_init(ResponseBodyViewClass* klass) {
    G_OBJECT_CLASS(klass)->dispose = response_body_view_dispose;
}

GtkWidget* response_body_view_new() {
    return g_object_new(RESPONSE_BODY_VIEW_TYPE, "orientation", GTK_ORIENTATION_HORIZONTAL, NULL);
}
